package cn.lg.soar.common.util.trans;

import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.common.util.reflect.ReflectUtil;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * @date 2022/8/31
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class TranslateHelpUtils {

    /**
     * 类型映射（处理集合、数组）
     * @param value
     * @param function 映射函数
     * @return
     */
    public static Object mapper(Object value, Function<Object, Object> function) {
        if (value instanceof Collection) {
            Collection<?> collection = (Collection<?>) value;
            return collection.stream().map(function).collect(Collectors.toList());
        }
        if (value.getClass().isArray()) {
            Object[] array = (Object[]) value;
            Object[] result = new Object[array.length];
            for (int i = 0; i < array.length; i++) {
                result[ i ] = function.apply(array[i]);
            }
            return result;
        }
        if (value instanceof Iterable) {
            List<Object> list = new ArrayList<>();
            Iterable<?> iterable = (Iterable<?>) value;
            iterable.forEach(x -> list.add(function.apply(x)));
            return list;
        }
        return null;
    }

    /**
     * 类型映射（处理集合、数组）
     * @param value
     * @param map 映射map
     * @return
     */
    public static Object mapper(Object value, Map<?, String> map) {
        if (value instanceof Collection) {
            Collection<?> collection = (Collection<?>) value;
            return collection.stream().map(map::get).collect(Collectors.toList());
        }
        if (value.getClass().isArray()) {
            Object[] array = (Object[]) value;
            List<String> list = new ArrayList<>(array.length);
            for (int i = 0; i < array.length; i++) {
                list.add(map.get(array[i]));
            }
            return list;
        }
        if (value instanceof Iterable) {
            List<String> list = new ArrayList<>();
            Iterable<?> iterable = (Iterable<?>) value;
            iterable.forEach(x -> list.add(map.get(x)));
            return list;
        }
        return null;
    }

    /**
     * 反向映射，字符串转java类型（处理集合、数组）
     * @param javaType java类型
     * @param value
     * @param function 映射函数
     * @return
     */
    public static Object remapper(Class<?> javaType, String value, Function<Object, Object> function) {
        String[] strings = value.split(", ");
        if (List.class.isAssignableFrom(javaType)) {
            ArrayList<Object> list = new ArrayList<>(strings.length);
            for (String x : strings) {
                list.add(function.apply(x));
            }
            return list;
        }
        if (Set.class.isAssignableFrom(javaType)) {
            Set<Object> set = new HashSet<>(strings.length);
            for (String x : strings) {
                set.add(function.apply(x));
            }
            return set;
        }
        if (javaType.isArray()) {
            Class<?> componentType = javaType.getComponentType();
            ArrayList<Object> list = new ArrayList<>(strings.length);
            for (String x : strings) {
                list.add(DataUtil.to(componentType, function.apply(x)));
            }
            return list.toArray(ReflectUtil.newArray(componentType, list.size()));
        }
        return null;
    }

    /**
     * 反向映射，字符串转java类型（处理集合、数组）
     * @param javaType java类型
     * @param value
     * @param map 映射map
     * @return
     */
    public static Object remapper(Class<?> javaType, String value, Map<String, Object> map) {
        String[] strings = value.split(", ");
        if (List.class.isAssignableFrom(javaType)) {
            ArrayList<Object> list = new ArrayList<>(strings.length);
            for (String x : strings) {
                list.add(map.get(x));
            }
            return list;
        }
        if (Set.class.isAssignableFrom(javaType)) {
            Set<Object> set = new HashSet<>(strings.length);
            for (String x : strings) {
                set.add(map.get(x));
            }
            return set;
        }
        if (javaType.isArray()) {
            String className = javaType.getName();
            className = className.substring(2, className.length() - 1);
            Class<?> aClass;
            try {
                aClass = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            ArrayList<Object> list = new ArrayList<>(strings.length);
            for (String x : strings) {
                list.add(DataUtil.to(aClass, map.get(x)));
            }
            return list.toArray(ReflectUtil.newArray(aClass, list.size()));
        }
        return null;
    }

}
